package base.core.util;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author Pengwei
 * @CreatDate 2021/12/24 21:33
 */
public class Beans {
    private static ObjectMapper objectMapper = Jacksons.getObjectMapper();

    /**
     * 将对象转换为String
     */
    public static String asString(Object object) {
        try {
            if (object == null) {
                return null;
            }
            if (object instanceof String) {
                return (String) object;
            }
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 复制属性
     *
     * @param ignoreProperties 忽略的属性
     */
    public static <T> T copy(Object source, Class<T> target, String... ignoreProperties) {
        if (source == null || target == null) {
            return null;
        }
        try {
            T t = target.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source, t, ignoreProperties);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 复制属性
     *
     * @param ignoreProperties 忽略的属性
     */
    public static <T> T copy(Object source, T target, String... ignoreProperties) {
        if (source == null || target == null) {
            return target;
        }
        try {
            BeanUtils.copyProperties(source, target, ignoreProperties);
            return target;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 复制属性
     *
     * @param ignoreProperties 忽略的属性
     */
    public static <T> List<T> copyList(Collection source, Class<T> target, String... ignoreProperties) {
        if (CollectionUtils.isEmpty(source) || target == null) {
            return new ArrayList();
        }
        try {
            return (List<T>) source.stream().map(o -> copy(o, target, ignoreProperties)).collect(Collectors.toList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList();
    }

    /**
     * 复制Page属性
     */
    public static <T> Page<T> copyPage(Page sourcePage, Class<T> target, String... ignoreProperties) {
        if (sourcePage == null || target == null) {
            return null;
        }
        Page<T> targetPage = copy(sourcePage, Page.class);
        targetPage.setRecords(copyList(sourcePage.getRecords(), target));
        return targetPage;
    }

    /**
     * 反序列化对象
     */
    public static <T> T asObj(Object source, Class<T> target) {
        if (source == null) {
            return null;
        }
        try {
            T t = objectMapper.readValue(asString(source), target);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反序列化对象
     */
    public static <T> T asObj(Object source, TypeReference<T> target) {
        if (source == null) {
            return null;
        }
        try {
            T t = objectMapper.readValue(asString(source), target);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反序列化对象
     */
    public static <T> T asObj(Object source, JavaType target) {
        if (source == null) {
            return null;
        }
        try {
            T t = objectMapper.readValue(asString(source), target);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 反序列化对象
     */
    public static <T> List<T> asList(Object source, Class<T> target) {
        if (source == null || target == null) {
            return new ArrayList<>();
        }
        try {
            JavaType javaType = objectMapper.getTypeFactory().constructType(new TypeReference<List>() {
            });
            List<Map> mapList = objectMapper.readValue(asString(source), javaType);
            List<T> targetList = mapList.stream().map(map -> asObj(map, target)).collect(Collectors.toList());
            return targetList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    public static String[] getNullPropertyNames(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null)
                emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }
}
